#include "Triangle3d.h"


Triangle3d::Triangle3d(Point3d i_point1,Point3d i_point2,Point3d i_point3)
  : m_point1(i_point1), m_point2(i_point2), m_point3(i_point3)
  {

  }

Point3d Triangle3d::GetPoint(int i_what_point)
  {
  if(i_what_point == 1)
    return m_point1;
  if(i_what_point == 2)
    return m_point2;
  else
    return m_point3;
  }
void Triangle3d::GetAllPoints(Point3d &o_point1, Point3d &o_point2, Point3d &o_point3)
  {
  o_point1 = m_point1;
  o_point2 = m_point2;
  o_point3 = m_point3;
  }

void Triangle3d::SetPoints(Point3d i_point1,Point3d i_point2,Point3d i_point3)
  {
  m_point1 = i_point1;
  m_point2 = i_point2;
  m_point3 = i_point3;
  }

bool Triangle3d::IsTriangleAndLineIntersects( Line3d i_line)
  {
  //is first plane of line is the same plane than contain triangle
  if( i_line.GetPlane(1).IsSame(Plane3d((*this))))
    return true;
  //is second plane of line is the same plane than contain triangle
  if( i_line.GetPlane(2).IsSame(Plane3d((*this))))
    return true;

  //making canonical equation of line using one point
  // of line and directive vector
  
  //making y = 0 for planes of line
  double a1 = i_line.GetPlane(1).GetA();
  double a2 = i_line.GetPlane(2).GetA();
  double b1 = i_line.GetPlane(1).GetB();
  double b2 = i_line.GetPlane(2).GetB();
  double c1 = i_line.GetPlane(1).GetC();
  double c2 = i_line.GetPlane(2).GetC();
  double d1 = i_line.GetPlane(1).GetD();
  double d2 = i_line.GetPlane(2).GetD();
 
  //taking point M(xp, 0, zp)
  //i_line contains point M
  double zp = (a2*d1 - a1*d2) / (a1*c2 - c1*a2);
  double yp = 0;
  double xp = (-c1 * zp - d1) / a1;
  
  //finding directive vector p = normal1 ^ normal2
  Vector3d p = Vector3d(a1, b1, c1) ^ Vector3d(a2, b2, c2);

  //canonical equation
  // (x-xp)/p1 = y/p2 = (z-zp)/p3
  double p1 = p.GetX();
  double p2 = p.GetY();
  double p3 = p.GetZ();

  //a, b, c, d - parameters of plane where triangle is situated
  Plane3d from_triangle((*this));
  double a = from_triangle.GetA();
  double b = from_triangle.GetB();
  double c = from_triangle.GetC();
  double d = from_triangle.GetD();

  //using this canonical equation
  //we will write parametrical equation for i_line
  //x = xp + p1*t
  //y = yp + p2*t
  //z = zp + p3*t
  double t = - (a * xp + b * yp + c * zp + d) / (a * p1 + b * p2 + c * p3);

  //finding coordinates where line intersects with plane
  double inter_x = xp + p1 * t;
  double inter_y = yp + p2 * t;
  double inter_z = zp + p3 * t;
  Point3d inter(inter_x, inter_y, inter_z);

  //checking if point is in the triangle
  //sum of angles AOB, BOC, COA, when O - inter point
  // == 2*PI
  Vector3d AO(this->GetPoint(1), inter);
  Vector3d OB(inter, this->GetPoint(2));
  double angle_AOB = AO.GetAngle(OB);

  Vector3d BO(this->GetPoint(2), inter);
  Vector3d OC(inter, this->GetPoint(3));
  double angle_BOC = BO.GetAngle(OC);

  Vector3d CO(this->GetPoint(3), inter);
  Vector3d OA(inter, this->GetPoint(1));
  double angle_COA = CO.GetAngle(OA);

  if(fabs(angle_AOB + angle_BOC + angle_COA - 360) < EPS)
    return true;
  else
    return false;

  }

bool Triangle3d::IsTrianglesIntersects( Triangle3d i_triangle)
  {
  Plane3d plane1((*this));
  Plane3d plane2(i_triangle);
  
  if(plane1.IsParallel(plane2))
    return false;
  if(plane1.IsSame(plane2))
    return true;
  if(plane1.IsPerpendicular(plane2))
    return true;

  Line3d inter_line(plane1, plane2);

  //first check
  bool is_first = this->IsTriangleAndLineIntersects(inter_line);
  //second check
  bool is_second = i_triangle.IsTriangleAndLineIntersects(inter_line);

  if( is_first && is_second )
    return true;
  else
    return false;
  }
